#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "shogi.h"

//------------------------------------------------------------
// board_init()
//------------------------------------------------------------
void board_init()
{
  // nothing to do
}

//------------------------------------------------------------
// board_t::clear()
//------------------------------------------------------------
void board_t::clear()
{
  memset(this,0,sizeof(board_t));
  for (int i=0;i<256;i++) {
    if (POS_IS_OB(i)) square[i]=OB;
  }
}

//------------------------------------------------------------
// board_t::build() : INPUT = turn, square[], hand[].
//------------------------------------------------------------
void board_t::build()
{
  int x,y,pos,pc,k;

  Board<WHITE> wb(*this);
  Board<BLACK> bb(*this);

  square64=0;
  if (turn==BLACK) square64=~square64;

  for (x=1;x<=9;x++) for (y=1;y<=9;y++) {
    pc=square[pos=POS(x,y)];
    if (pc==0 || pc==OB) continue;
    else if (PC_K(pc)==OU) king[PC_C(pc)]=pos;
    else if (PC_K(pc)==FU) pawn[PC_C(pc)][x]=pos;
    square64^=R64(pos,pc);
    //if (PC_C(pc)==WHITE) wb.effect_update();
    //if (PC_C(pc)==BLACK) bb.effect_update();
  }

  for (k=FU; k<=HI; k++) {
    hand32[WHITE]+=H32(k)*hand[WHITE][k];
    hand32[BLACK]+=H32(k)*hand[BLACK][k];
  }
}

//------------------------------------------------------------
// board_t::init()
//------------------------------------------------------------
void board_t::init(Handicap handi)
{
  if (handi!=HIRATE) {
    fputs("supported handicap is HIRATE only.",stderr);
    assert(false);
  }

  clear();

  turn=WHITE;

  int placement[40][2] = {
    {0x59,OU_w},{0x51,OU_b},
    {0x28,HI_w},{0x82,HI_b},
    {0x22,KA_b},{0x88,KA_b},
    {0x69,KI_w},{0x49,KI_w},{0x61,KI_b},{0x41,KI_b},
    {0x79,GI_w},{0x39,GI_w},{0x71,GI_b},{0x31,GI_b},
    {0x89,KE_w},{0x29,KE_w},{0x81,KE_b},{0x21,KE_b},
    {0x99,KY_w},{0x19,KY_w},{0x91,KY_b},{0x11,KY_b},
    {0x97,FU_w},{0x87,FU_w},{0x77,FU_w},
    {0x67,FU_w},{0x57,FU_w},{0x47,FU_w},
    {0x37,FU_w},{0x27,FU_w},{0x17,FU_w},
    {0x93,FU_b},{0x83,FU_b},{0x73,FU_b},
    {0x63,FU_b},{0x53,FU_b},{0x43,FU_b},
    {0x33,FU_b},{0x23,FU_b},{0x13,FU_b},
  };

  for (int i=0;i<40;i++)
  {
    int pos=placement[i][0];
    int pc=placement[i][1];
    square[pos]=pc;
  }

  build();
}

//------------------------------------------------------------
// board_t::copy_to()
//------------------------------------------------------------
void board_t::copy_to(board_t& that)
{
  that.clear();
  for (int i=0; i<256; i++)
  {
    if (!POS_IS_OB(i)) that.square[i]=square[i];
  }
  for (int k=FU; k<=HI; k++)
  {
    that.hand[WHITE][k]=hand[WHITE][k];
    that.hand[BLACK][k]=hand[BLACK][k];
  }
  that.turn=turn;
  that.build();
}

//------------------------------------------------------------
// board_t::is_consistent()
//------------------------------------------------------------
#define SZ sizeof(board_t)
bool board_t::is_consistent()
{
  board_t b1,b2;

  copy_to(b1);
  memcpy(&b2,this,SZ);

  b1.counter=b2.counter;
  for (int i=0;i<CounterMax;i++)
  {
    b1.undo[i]=b2.undo[i];
  }

  char a1[SZ],a2[SZ];
  memcpy(a1,&b1,SZ);
  memcpy(a2,&b2,SZ);

  for (int i=0;i<SZ;i++)
  {
    if (a1[i]!=a2[i]) {
        printf("BHC: not equal at [%d] %x vs %x\n",i,a1[i],a2[i]);
        puts("--input");
        b1.print_ef();
        puts("--copy");
        b2.print_ef();
        return false;
    }
  }
  return true;
}
#undef SZ

//------------------------------------------------------------
// board_t::print_ef()
//------------------------------------------------------------
void board_t::print_ef()
{
}

